<?php


namespace app\api\service;

use app\api\model\Order as OrderModel;
use app\api\model\OrderProduct as OrderProductModel;
use app\api\model\Product as ProductModel;
use app\api\model\Sku as SkuModel;
use app\api\model\UserAddress;
use app\api\model\UserAddress as UserAddressModel;
use app\common\enum\FlagEnum;
use app\common\exception\OrderException;
use think\Db;


class Order
{
    //订单商品信息
    protected $o_products;
    //真实商品包括库存量
    protected $products;
    //当前用户id
    protected $uid;
    //当前订单地址id号
    protected $address_id;

    public function place($uid, $address_id, $o_products)
    {
        $this->uid = $uid;
        $this->address_id = $address_id;
        $this->o_products = $o_products;
        $this->products = $this->getProductsByOrder($o_products);
        //库存量检测
        $status = $this->getOrderStatus();
        if (!$status['pass']) {
            $status['order_id'] = -1;
            return $status;
        }
        //开始创建订单,先创建订单快照
        $order_snap = $this->snapOrder($status);
        //创建订单
        $order = $this->createOrder($order_snap);
        $order['pass'] = true;
        return $order;
    }

    private function createOrder($order_snap)
    {
        Db::startTrans();
        try {
            $order_no = self::makeOrderNo();
            $order = new OrderModel();
            $order->user_id = $this->uid;
            $order->order_no = $order_no;
            $order->total_price = $order_snap['total_price'];
            $order->total_count = $order_snap['total_count'];
            $order->snap_name = $order_snap['snap_name'];
            $order->snap_img = $order_snap['snap_img'];
            $order->snap_address = $order_snap['snap_address'];
            $order->snap_items = json_encode($order_snap['p_status'], JSON_UNESCAPED_UNICODE);
            $order->save();

            $order_id = $order->id;
            $create_time = $order->create_time;
            foreach ($this->o_products as &$p) {
                $p['order_id'] = $order_id;
            }
            $order_product = new OrderProductModel();
            $order_product->saveAll($this->o_products);

            Db::commit();
            return [
                'order_no' => $order_no,
                'order_id' => $order_id,
                'create_time' => $create_time
            ];
        } catch (\Exception $ex) {
            Db::rollback();
            throw $ex;
        }
    }

    public static function makeOrderNo()
    {
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $order_no =
            $yCode[intval(date('Y')) - 2017] . strtoupper(dechex(date('m'))) . date(
                'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf(
                '%02d', rand(0, 99));
        return $order_no;
    }

    private function snapOrder($status)
    {
        $snap = [
            'total_price' => 0,
            'total_count' => 0,
            'snap_name' => '',
            'snap_img' => '',
            'snap_address' => null,
            'p_status' => []
        ];

        $snap['total_price'] = $status['total_price'];
        $snap['total_count'] = $status['total_count'];
        $snap['p_status'] = $status['p_status_array'];
        $snap['snap_name'] = $this->products[0]['title'];
        $snap['snap_img'] = $this->products[0]['img'];
        $snap['snap_address'] = $this->getUserAddress($this->uid, $this->address_id);
        if (count($this->products) > 1) {
            $snap['snap_name'] .= '等';
        }
        return $snap;
    }

    public function checkOrderStatus($order_id)
    {
        $o_products = OrderProductModel::where('order_id', '=', $order_id)->select();
        $this->o_products = $o_products;
        $this->products = $this->getProductsByOrder($o_products);
        $status = $this->getOrderStatus();
        return $status;
    }

    // 库存量检测就是对比$this->products和$this->o_products
    private function getOrderStatus()
    {
        $status = [
            'pass' => true,
            'total_price' => 0,
            'total_count' => 0,
            'p_status_array' => []
        ];

        foreach ($this->o_products as $o_product) {
            $p_status = $this->getProductStatus($o_product['item_id'], $o_product['count'], $this->products);
            if (!($p_status['has_stock'])) {
                $status['pass'] = false;
            }
            $status['total_price'] += $p_status['total_price'];
            $status['total_count'] += $p_status['count'];
            array_push($status['p_status_array'], $p_status);
        }

        return $status;
    }

    //$products数据库中取出的数据
    //$o_pid是订单中item_id号
    private function getProductStatus($o_item_id, $o_count, $products)
    {
        $p_index = -1;
        $p_status = [
            'id' => null,
            'title' => '',
            'count' => 0,
            'total_price' => 0,
            'has_stock' => false,
            'flag' => 0,
        ];

        for ($i = 0; $i < count($products); $i++) {
            if ($o_item_id == $products[$i]['id']) {
                $p_index = $i;
            }
        }

        if ($p_index == -1) {
            throw new OrderException(['msg' => 'id为' . $o_item_id . '的商品不存在，创建订单失败']);
        } else {
            $product = $products[$p_index];
            $p_status['id'] = $product['id'];
            $p_status['title'] = $product['title'];
            $p_status['count'] = $o_count;
            $p_status['total_price'] = $product['price'] * $o_count;
            if ($product['stock'] - $o_count >= 0) {
                $p_status['has_stock'] = true;
            }
            $p_status['flag'] = $product['flag'];
        }
        return $p_status;
    }

    //根据订单商品信息查找真实商品信息
    private function getProductsByOrder($oProducts)
    {
        $oPSingleIDs = [];
        $oPMutilpleIDs = [];
        foreach ($oProducts as $value) {
            if ($value['flag'] == FlagEnum::Single) {
                array_push($oPSingleIDs, $value['item_id']);
            }
            if ($value['flag'] == FlagEnum::Multiple) {
                array_push($oPMutilpleIDs, $value['item_id']);
            }
        }

        $single = ProductModel::all($oPSingleIDs)
            ->visible(['id','price','title','img','stock'])
//            ->append('flag')
            ->toArray();
        if($single) {
            foreach($single as $key => &$value){
                $value['flag'] = FlagEnum::Single;
            }
        }

        $mutilple = SkuModel::all($oPMutilpleIDs)
            ->visible(['id', 'price', 'title', 'img', 'stock'])
//            ->append('flag')
            ->toArray();

        if($mutilple){
            foreach($mutilple as $key => &$value){
                $value['flag'] = FlagEnum::Multiple;
            }
        }

        return array_merge($single, $mutilple);
    }

    private function getUserAddress($user_id, $address_id)
    {
        $address = UserAddressModel::where(['user_id' => $user_id, 'id' => $address_id])->find();
        if (empty($address)) {
            throw new UserException([
                'msg' => "{$user_id}号用户的地址不存在, 下单失败",
                'code' => 60001
            ]);
        }
        return $address->toJson();
    }

}